Passed
Branch wip_sessions (830972)
by Nils
07:55
created

install.js ➔ checkPage   F

Complexity

Conditions 21

Size

Total Lines 201
Code Lines 138

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 21
eloc 138
dl 0
loc 201
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like install.js ➔ checkPage often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*
2
 * Teampass - a collaborative passwords manager.
3
 * ---
4
 * This library is distributed in the hope that it will be useful,
5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7
 * ---
8
 * @project   Teampass
9
 * @version   
10
 * @file      install.js
11
 * ---
12
 * @author    Nils Laumaillé ([email protected])
13
 * @copyright 2009-2023 Teampass.net
14
 * @license   https://spdx.org/licenses/GPL-3.0-only.html#licenseText GPL-3.0
15
 * ---
16
 * @see       https://www.teampass.net
17
 */
18
19
20
$(function() {    
21
    $("#but_next").click(function(event) {
0 ignored issues
show
Unused Code introduced by
The parameter event is not used and could be removed.

This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.

Loading history...
22
        $("#step").val($(this).attr("target_id"));
23
        document.upgrade.submit();
24
    });
25
26
    // no paste
27
    $("#admin_pwd").bind("paste",function(e) {
28
        alert("Paste option is disabled !!");
0 ignored issues
show
Debugging Code Best Practice introduced by
The alert UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
29
        e.preventDefault();
30
    });
31
    
32
    /*
33
    * Removing automatic action
34
    // Auto start
35
    if ($("#step").val() == 5) {
36
        $('#but_launch').trigger('click');
37
    }
38
    */
39
});
40
41
function aesEncrypt(text)
42
{
43
    return Aes.Ctr.encrypt(text, "cpm", 128);
44
}
45
46
var global_error_on_query = false,
47
    step = "",
48
    dataToUse = "",
49
    dbInfo = "",
50
    index = "",
51
    multiple = "",
52
    jsonValues = "";
53
54
function checkPage()
55
{
56
    step = $("#step").val();
57
    dataToUse = "";
58
    error = "";
0 ignored issues
show
Bug introduced by
The variable error seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.error.
Loading history...
59
    index = "";
60
    tasks = [];
0 ignored issues
show
Bug introduced by
The variable tasks seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.tasks.
Loading history...
61
    dbInfo = [];
62
    multiple = "";
63
    tsk = "";
0 ignored issues
show
Bug introduced by
The variable tsk seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.tsk.
Loading history...
64
    $("#step_error").addClass("hidden").html("");
65
    $("#res_"+step).html("");
66
    
67
    alertify
68
        .message('Working on it... <i class="fas fa-cog fa-spin fa-2x"></i>', 0)
69
        .dismissOthers();
70
71
    if (step === "2") {
72
    // STEP 2
73
        if ($("#url_path").val() === "" || $("#absolute_path").val() === "") {
74
            error = "Fields need to be filled in!";
75
        } else {
76
            jsonValues = {"absolute_path":$("#absolute_path").val(), "url_path":$("#url_path").val()};
77
            dataToUse = JSON.stringify(jsonValues);
78
            tasks = ["folder*install", "folder*includes", "folder*includes/config", "folder*includes/avatars", "folder*includes/libraries/csrfp/libs", "folder*includes/libraries/csrfp/js", "folder*includes/libraries/csrfp/log",  "extension*mbstring", "extension*openssl", "extension*bcmath", "extension*iconv", "extension*gd", "extension*xml", "extension*curl", "version*php", "ini*max_execution_time", "extension*gmp", "folder*files", "folder*upload"];
79
            multiple = true;
80
            $("#hid_absolute_path").val($("#absolute_path").val());
81
            $("#hid_url_path").val($("#url_path").val());
82
        }
83
    } else if (step === "3") {
84
    // STEP 3
85
        if ($("#db_host").val() === "" || $("#db_db").val() === "" || $("#db_login").val() === "" || $("#db_port").val() === "") {
86
            error = "Fields need to be filled in!";
87
        } else if ($("#db_pw").val().indexOf('"') > -1) {
88
            error = "Double quotes in password not allowed!";
89
        } else {
90
            jsonValues = {"db_host":$("#db_host").val(), "db_bdd":$("#db_bdd").val(), "db_login":$("#db_login").val(), "db_pw":$("#db_pw").val(), "db_port":$("#db_port").val(), "absolute_path":$("#hid_absolute_path").val(), "url_path":$("#hid_url_path").val()};
91
            dataToUse = JSON.stringify(jsonValues);
92
            tasks = ["connection*test"];
93
            multiple = "";
94
            $("#hid_db_host").val($("#db_host").val());
95
            $("#hid_db_bdd").val($("#db_bdd").val());
96
            $("#hid_db_login").val($("#db_login").val());
97
            $("#hid_db_pwd").val($("#db_pw").val());
98
            $("#hid_db_port").val($("#db_port").val());
99
        }
100
    } else if (step === "4") {
101
    // STEP 4
102
        if ($("#admin_pwd").val() === "") {
103
            alertify
104
                .error('<i class="fas fa-ban mr-2"></i>You must define a password for Administrator account.', 10)
105
                .dismissOthers();
106
            return false;
107
        } else if ($("#admin_pwd_confirm").val() === "") {
108
            alertify
109
                .error('<i class="fas fa-ban mr-2"></i>You must confirm the password for Administrator account.', 10)
110
                .dismissOthers();
111
            return false;
112
        } else if ($("#admin_pwd_confirm").val() !== $("#admin_pwd").val()) {
113
            alertify
114
                .error('<i class="fas fa-ban mr-2"></i>Administrator passwords are not similar.', 10)
115
                .dismissOthers();
116
            return false;
117
        } else{
118
            $("#hid_db_pre").val($("#tbl_prefix").val());
119
            jsonValues = {"tbl_prefix":sanitizeString($("#tbl_prefix").val()), "sk_path":sanitizeString($("#sk_path").val()), "admin_pwd":sanitizeString($("#admin_pwd").val()), "send_stats":""};
120
            dataToUse = JSON.stringify(jsonValues);
121
            tasks = ["misc*preparation"];
122
            multiple = "";
123
        }
124
    } else if (step === "5") {
125
    // STEP 5
126
        dataToUse = "";
127
        tasks = ["table*utf8", "table*api", "table*automatic_del", "table*cache", "table*cache_tree", "table*categories", "table*categories_folders", "table*categories_items", "table*defuse_passwords", "table*emails", "table*export", "table*files", "table*items", "table*items_change", "table*items_edition", "table*items_otp", "table*kb", "table*kb_categories", "table*kb_items", "table*ldap_groups_roles", "table*languages", "table*log_items", "table*log_system", "table*misc", "table*nested_tree", "table*notification", "table*otv", "table*processes", "table*processes_tasks", "table*processes_logs", "table*restriction_to_roles", "table*rights", "table*roles_title", "table*roles_values", "table*sharekeys_fields", "table*sharekeys_files", "table*sharekeys_items", "table*sharekeys_logs", "table*sharekeys_suggestions", "table*suggestion", "table*tags", "table*templates", "table*tokens", "table*users"];
128
        multiple = true;
129
    } else if (step === "6") {
130
    // STEP 6
131
        jsonValues = {"url_path":sanitizeString($("#hid_url_path").val())};
132
        dataToUse = JSON.stringify(jsonValues);
133
        tasks = ["install*init", "file*security", "file*settings.php", "file*csrfp-token", "install*cleanup", "install*cronJob"];
134
        multiple = true;
135
    }
136
137
    // launch query
138
    if (error === "" && multiple === true) {
139
        global_error_on_query = false;
140
        index = 0;
141
        dbInfo = {"db_host" : $("#hid_db_host").val(), "db_bdd" : $("#hid_db_bdd").val(), "db_login" : $("#hid_db_login").val(), "db_pw" : $("#hid_db_pwd").val(), "db_port" : $("#hid_db_port").val(), "db_pre" : $("#hid_db_pre").val()};
142
143
        $("#step_res").val("true");
144
        $("#pop_db").html("");
145
146
        var promise = tasks.slice(1)
147
            .reduce(
148
                (a,b) => a.then(doGetJson.bind(null, b)),
0 ignored issues
show
Unused Code introduced by
The call to bind does not seem necessary since the function doGetJson declared on line 260 does not use this.
Loading history...
149
                doGetJson(
150
                    tasks[0]
151
                )
152
            );
153
154
        promise.then(function(){
155
            // do something when all requests are ready
156
            // all requests are complete
157
            if ($("#step_res").val() === "false" || global_error_on_query === true) {
158
                alertify
159
                    .error('<i class="fas fa-ban mr-2"></i>At least one task has failed! Please correct and relaunch.', 0)
160
                    .dismissOthers();
161
                return false;
162
            } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
163
                alertify
164
                    .success('<i class="fas fa-check text-success mr-2"></i><b>Done</b>.<br>Click next to continue', 1)
165
                    .dismissOthers();
166
167
                    $("#but_launch")
168
                    .prop("disabled", true)
169
                    .addClass("hidden");
170
                $("#but_next")
171
                    .prop("disabled", false)
172
                    .removeClass("hidden");
173
                // Hide restart button at end of step 6 if successful
174
                if (step === "6") {
0 ignored issues
show
Complexity Best Practice introduced by
There is no return statement if step === "6" is false. Are you sure this is correct? If so, consider adding return; explicitly.

This check looks for functions where a return statement is found in some execution paths, but not in all.

Consider this little piece of code

function isBig(a) {
    if (a > 5000) {
        return "yes";
    }
}

console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined

The function isBig will only return a specific value when its parameter is bigger than 5000. In any other case, it will implicitly return undefined.

This behaviour may not be what you had intended. In any case, you can add a return undefined to the other execution path to make the return value explicit.

Loading history...
175
                    $("#but_restart")
176
                        .prop("disabled", true)
177
                        .addClass("hidden");
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
178
                }
179
                
180
                /*
181
                * Removing automatic action
182
                // Go to next step
183
                if (step <= 6) {
184
                    setTimeout(
185
                        function(){
186
                            $('#but_next').trigger('click');
187
                        },
188
                        1000
189
                    );
190
                }
191
                */
192
            }
193
        });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
194
    } else if (error === "" && multiple === "") {
195
        tsk = tasks[0].split("*");
196
197
        dbInfo = {"db_host" : $("#hid_db_host").val(), "db_bdd" : $("#hid_db_bdd").val(), "db_login" : $("#hid_db_login").val(), "db_pw" : $("#hid_db_pwd").val(), "db_port" : $("#hid_db_port").val()};
198
199
        dataToUse = {
200
            type:       "step_"+step,
201
            data:       aesEncrypt(dataToUse),
202
            activity:   aesEncrypt(tsk[0]),
203
            task:       aesEncrypt(tsk[1]),
204
            db:         aesEncrypt(JSON.stringify(dbInfo)),
205
            index:      index,
206
            multiple:   multiple,
207
            info:       tsk[0]+"-"+tsk[1],
208
        }
209
210
        $.ajax({
211
            url: "install.queries.php",
212
            type : 'POST',
213
            dataType : "json",
214
            data : dataToUse,
215
            complete : function(data){
216
                data = $.parseJSON(data.responseText);
217
                
218
                if (data[0].error !== "" ) {
219
                    alertify
220
                        .error('<i class="fas fa-ban mr-2"></i>Next ERROR occurred: <i>' + data[0].error + '</i><br />Please correct and relaunch.', 0)
221
                        .dismissOthers();
222
                    return false;
223
                } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
224
                    if (data[0].result !== undefined && data[0].result !== "" ) {
225
                        alertify
226
                            .success('<i class="fas fa-check text-success mr-2"></i>' + data[0].result + '.<br>Click next to continue', 0)
227
                            .dismissOthers();
228
                    }
229
                    $("#but_launch")
230
                        .prop("disabled", true)
231
                        .addClass("hidden");
232
                    $("#but_next")
233
                        .prop("disabled", false)
234
                        .removeClass("hidden");
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
235
                }
236
                
237
                /*
238
                * Removing automatic action
239
                // Go to next step
240
                if (step <= 6) {
241
                    setTimeout(
242
                        function(){
243
                            $('#but_next').trigger('click');
244
                        },
245
                        1000
246
                    );
247
                }
248
                */
249
            }
250
        });
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
251
    } else {
252
        $("#step_error").removeClass("hidden").html(error);
0 ignored issues
show
Best Practice introduced by
There is no return statement in this branch, but you do return something in other branches. Did you maybe miss it? If you do not want to return anything, consider adding return undefined; explicitly.
Loading history...
253
    }
254
}
255
256
/**
257
 * 
258
 * @param {string} task Task in string format
259
 */
260
function doGetJson(task)
261
{
262
    console.log("\n\n--- PREPARATION---\n"+step+"\n"+dataToUse+"\n"+dbInfo+"\n"+index+"\n"+multiple+"\n"+task+"\n-------\n")
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
263
    tsk = task.split("*");
0 ignored issues
show
Bug introduced by
The variable tsk seems to be never declared. Assigning variables without defining them first makes them global. If this was intended, consider making it explicit like using window.tsk.
Loading history...
264
265
    return $.ajax({
266
        url: "install.queries.php",
267
        type : "POST",
268
        dataType : "json",
269
        async: false,
270
        data : {
271
            type:       "step_"+step,
272
            data:  aesEncrypt(dataToUse), //
273
            activity:   aesEncrypt(tsk[0]),
274
            task:       aesEncrypt(tsk[1]),
275
            db:         aesEncrypt(JSON.stringify(dbInfo)),
276
            index:      index,
277
            multiple:   multiple,
278
            info:       tsk[0]+"-"+tsk[1]
279
        }
280
    })
281
    .complete(function(data) {
282
        console.log("\n\n--- RECEPTION---\n"+data+"\n-------\n")
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
283
        if (data.responseText === "") {
284
            alertify
285
                .error('<i class="fas fa-ban mr-2">[ERROR] Answer from server is empty.', 10)
286
                .dismissOthers();
287
        } else {
288
            data = $.parseJSON(data.responseText);
289
            console.log("RETOUR:");
290
            console.log(data)
291
            if (data[0].error === "") {
292
                if (step === "5") {
293
                    if (data[0].activity === "table") {
294
                        $("#pop_db").append("<li>Table <b>"+data[0].task+"</b> created</li>");
295
                    } else if (data[0].activity === "entry") {
296
                        $("#pop_db").append("<li>Entries <b>"+data[0].task+"</b> were added</li>");
297
                    }
298
                } else {
299
                    $("#res"+step+"_check"+data[0].index).html('<i class="fas fa-check text-success"></i>');
300
                    $("#res"+step+"_check99").html('<i class="fas fa-check text-success"></i>');
301
                }
302
303
                if (data[0].result !== undefined && data[0].result !== "" ) {
304
                    alertify
305
                        .message(data[0].result, 10)
306
                        .dismissOthers();
307
                }
308
            } else {
309
                $("#res"+step+"_check"+data[0].index).html('<span class="badge badge-danger"><i class="fas fa-ban text-warning mr-2"></i>' + data[0].error + "</i></span>");
310
                                            
311
                global_error_on_query = true;
312
            }
313
        }
314
        index++;
315
    });
316
}
317
318
319
function GotoNextStep()
320
{
321
    var step = $("#page_id").val(),
322
    nextStep = parseInt(step) + 1;
323
324
    if (nextStep === 7) {
325
        $("#but_restart, #but_next, #but_launch").addClass("hidden");
326
        $("#but_start").addClass("hidden");
327
        $("#step_result").html("").addClass("hidden");
328
        $("#step_name").html($("#menu_step"+nextStep).html());
329
        $("#step_content").html($("#text_step"+nextStep).html());
330
        $("#menu_step"+step).switchClass("li_inprogress", "li_done");
331
        $("#menu_step"+nextStep).switchClass("", "li_inprogress");
332
        $("#res_"+step).html("<img src=\"images/tick.png\">");
333
    } else {
334
        $("#page_id").val(nextStep);
335
        $("#but_launch").removeClass("hidden").prop("disabled", false);
336
        $("#but_launch").removeClass("hidden");
337
        $("#but_restart").removeClass("hidden");
338
        $("#but_next").prop("disabled", true);
339
        $("#but_next").addClass("hidden");
340
        $("#menu_step"+step).switchClass("li_inprogress", "li_done");
341
        $("#menu_step"+nextStep).switchClass("", "li_inprogress");
342
        $("#res_"+step).html("<img src=\"images/tick.png\">");
343
        $("#step_result").html("");
344
        $("#step_name").html($("#menu_step"+nextStep).html());
345
        $("#step_content").html($("#text_step"+nextStep).html());
346
        $('#admin_pwd').live("paste",function(e) {
347
            alert("Paste option is disabled !!");
0 ignored issues
show
Debugging Code Best Practice introduced by
The alert UI element is often considered obtrusive and is generally only used as a temporary measure. Consider replacing it with another UI element.
Loading history...
348
            e.preventDefault();
349
        });
350
        $("#admin_pwd").live("keypress", function(e){
351
            var key = e.charCode || e.keyCode || 0;
352
            // allow backspace, tab, delete, arrows, letters, numbers and keypad numbers ONLY
353
            return (
354
                key !== 39
355
            );
356
        });
357
        // Auto start as required
358
        if (nextStep === "5" || nextStep === "6" ) {
359
            checkPage();
360
        }
361
    }
362
}
363